-- Operand Processing --

Op.Framed .offset (MEM (GR .ps 5) $ 1 .offset) :-
	Config.PointerSize .ps #

	-- Registers not assigned to any variable are changeable
Op.Mutable .reg :-
	Register.Temporary .reg; Register.Permanent .reg #

	-- Duplicates an operand value; remember to free it
Op.MakeCopy .op (.alias) :-
	Register.GetTransient .alias,
	Emit ("MOV" .alias .op) #

Op.Transfer .op1 .op2 :-
	(nth .op1 0 GR; nth .op2 0 GR; nth .op2 0 IMM),
	Emit ("MOV" .op1 .op2) ! #
Op.Transfer .op1 .op2 :-
	Register.GetTransient .trans,
	Emit ("MOV" .trans .op2),
	Emit ("MOV" .op1 .trans),
	Op.Free .trans #

	-- Transfer to a pointer
Op.PtrTransfer (IMM .d) .b :-
	Op.Transfer (MEM $ $ 1 .d) .b ! #
Op.PtrTransfer (GR .size .r) .b :-
	Config.PointerSize .size,
	Op.Transfer (MEM (GR .size .r) $ 1 0) .b ! #
Op.PtrTransfer .a .b :-
	Op.MakeCopy .a .trans,
	Op.PtrTransfer .trans .b,
	Op.Free .trans #

Op.Register .op :- nth .op 0 GR #

Op.Free .op :-
	Op.Register .op ! Register.Free .op #
Op.Free (MEM .base .index . .) :- !
	Op.Free .base, Op.Free .index #
Op.Free . #
